package com.xuecheng.orders.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xuecheng.base.exception.XueChengPlusException;
import com.xuecheng.base.utils.IdWorkerUtils;
import com.xuecheng.base.utils.QRCodeUtil;
import com.xuecheng.messagesdk.service.MqMessageService;
import com.xuecheng.orders.jobhandler.PayNotifyTask;
import com.xuecheng.orders.mapper.XcOrdersGoodsMapper;
import com.xuecheng.orders.mapper.XcOrdersMapper;
import com.xuecheng.orders.mapper.XcPayRecordMapper;
import com.xuecheng.orders.model.dto.AddOrderDto;
import com.xuecheng.orders.model.dto.PayRecordDto;
import com.xuecheng.orders.model.dto.PayStatusDto;
import com.xuecheng.orders.model.po.XcOrders;
import com.xuecheng.orders.model.po.XcOrdersGoods;
import com.xuecheng.orders.model.po.XcPayRecord;
import com.xuecheng.orders.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;

/**
 * ClassName: OrderServiceImpl
 * Package: com.xuecheng.orders.service.impl
 * Description:
 *
 * @Author Endeavor-ZQB
 * @Create 2023/2/20 16:09
 * @Version 1.0
 */
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    XcOrdersMapper xcOrdersMapper;

    @Autowired
    XcPayRecordMapper xcPayRecordMapper;

    @Autowired
    XcOrdersGoodsMapper xcOrdersGoodsMapper;


    @Autowired
    MqMessageService mqMessageService;

    @Value("${pay.alipay.APP_ID}")
    String APP_ID;

    @Transactional
    @Override
    public PayRecordDto createOrder(String userId, AddOrderDto addOrderDto) {
        //添加商品订单
        XcOrders orders = saveXcOrders(userId, addOrderDto);

        //添加支付交易记录
        XcPayRecord payRecord = createPayRecord(orders);
        PayRecordDto payRecordDto = new PayRecordDto();
        BeanUtils.copyProperties(payRecord,payRecordDto);

        //生成支付二维码
        String qrCode = null;
        try {
            //url要可以被模拟器访问到，url为下单接口(稍后定义)
            qrCode = new  QRCodeUtil().createQRCode("http://192.168.101.1/api/orders/requestpay?payNo="+payRecordDto.getPayNo(), 200, 200);

        }catch (IOException e) {
            XueChengPlusException.cast("生成二维码出错");
        }
        payRecordDto.setQrcode(qrCode);

        return payRecordDto;
    }

    @Override
    public XcPayRecord getPayRecordByPayNo(String payNo) {
        XcPayRecord payRecord = xcPayRecordMapper.selectOne(new LambdaQueryWrapper<XcPayRecord>().eq(XcPayRecord::getPayNo, payNo));
        return payRecord;
    }

    @Transactional
    @Override
    public void saveAliPayStatus(PayStatusDto payStatusDto) {
        //当支付成功才更新订单状态
        //支付结果
        String trade_status = payStatusDto.getTrade_status();
        if (trade_status.equals("TRADE_SUCCESS")){
            //根据支付流水号获取支付记录
            String payNo = payStatusDto.getOut_trade_no();
            XcPayRecord payRecord = getPayRecordByPayNo(payNo);

            //支付金额变为分
            Float totalPrice = payRecord.getTotalPrice() * 100;
            Float total_amount = Float.parseFloat(payStatusDto.getTotal_amount())*100;
            //检验是否一致
            if (payRecord != null && totalPrice.intValue() == total_amount.intValue() && payStatusDto.getApp_id().equals(APP_ID)){
                String status = payRecord.getStatus();
                if ("601001".equals(status)){ //未支付进行处理
                    log.debug("更新支付结果，支付交易流水号:{},支付结果:{}"+payNo,trade_status);
                    XcPayRecord payRecord_u = new XcPayRecord();
                    payRecord_u.setStatus("601002");   //支付成功
                    payRecord_u.setOutPayChannel("603002");
                    payRecord_u.setCreateDate(LocalDateTime.now());
                    payRecord_u.setPaySuccessTime(LocalDateTime.now());
                    payRecord_u.setOutPayNo(payStatusDto.getTrade_no());
                    LambdaQueryWrapper<XcPayRecord> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(XcPayRecord::getPayNo,payNo);
                    int update = xcPayRecordMapper.update(payRecord_u, queryWrapper);
                    if (update > 0){
                        log.info("收到支付通知，更新支付交易状态成功，支付流水号:{},支付结果:{}"+payNo,trade_status);
                    }else {
                        log.error("收到支付通知，更新支付交易状态失败，支付流水号:{},支付结果:{}"+payNo,trade_status);
                    }
                    //关联订单号
                    Long orderId = payRecord.getOrderId();
                    XcOrders orders = xcOrdersMapper.selectById(orderId);
                    if (orders != null){
                        //更新订单状态
                        XcOrders orders_u = new XcOrders();
                        orders_u.setStatus("600002");
                        int update1 = xcOrdersMapper.update(orders_u, new LambdaQueryWrapper<XcOrders>().eq(XcOrders::getId, orderId));
                        if (update1 > 0){
                            log.info("收到支付通知，更新订单状态成功，支付流水号:{},支付结果:{}，订单号:{},状态:{}"+payNo,trade_status,orderId,"600002");

                            //找到订单表所关联的外部业务系统的主键
                            String outBusinessId = orders.getOutBusinessId();
                            //添加消息记录 String messageType(标记为支付结果通知),String businessKey1,String businessKey2(具体订单业务类型),String businessKey3
                            mqMessageService.addMessage(PayNotifyTask.MESSAGE_TYPE,outBusinessId,orders.getOrderType(),null);

                        }else {
                            log.error("收到支付通知，更新订单状态失败，支付流水号:{},支付结果:{}，订单号:{},状态:{}"+payNo,trade_status,orderId,"600002");
                        }

                    }

                }
            }
        }
    }

    @Transactional
    public XcOrders saveXcOrders(String userId, AddOrderDto addOrderDto){
        //对订单插入进行幂等性处理
        XcOrders order = getOrderByBusinessId(addOrderDto.getOutBusinessId());
        if (order != null){
            return order;
        }
        order = new XcOrders();
        //生成订单号
        long orderId = IdWorkerUtils.getInstance().nextId();
        order.setId(orderId);
        order.setUserId(userId);
        order.setCreateDate(LocalDateTime.now());
        order.setStatus("600001");  //未支付
        order.setOrderDescrip(addOrderDto.getOrderDescrip());
        order.setOrderDetail(addOrderDto.getOrderDetail());
        order.setOrderName(addOrderDto.getOrderName());
        order.setOrderType(addOrderDto.getOrderType());
        order.setTotalPrice(addOrderDto.getTotalPrice());
        order.setOutBusinessId(addOrderDto.getOutBusinessId()); //选课记录id

        xcOrdersMapper.insert(order);
        String orderDetailJson = addOrderDto.getOrderDetail();
        //将json转为List
        List<XcOrdersGoods> xcOrdersGoodsList = JSON.parseArray(orderDetailJson, XcOrdersGoods.class);
        xcOrdersGoodsList.forEach(goods->{
            XcOrdersGoods xcOrdersGoods = new XcOrdersGoods();
            BeanUtils.copyProperties(goods,xcOrdersGoods);
            xcOrdersGoods.setOrderId(orderId); //订单号
            xcOrdersGoodsMapper.insert(xcOrdersGoods);
        });
        return order;

    }

    //根据业务id查询订单
    public XcOrders getOrderByBusinessId(String businessId) {
        XcOrders orders = xcOrdersMapper.selectOne(new LambdaQueryWrapper<XcOrders>().eq(XcOrders::getOutBusinessId, businessId));
        return orders;
    }

    public XcPayRecord createPayRecord(XcOrders orders){
        XcPayRecord payRecord = new XcPayRecord();
        //生成支付交易流水号
        long payNo = IdWorkerUtils.getInstance().nextId();
        payRecord.setPayNo(payNo);
        payRecord.setOrderId(orders.getId()); //商品订单号
        payRecord.setCreateDate(LocalDateTime.now());
        payRecord.setOrderName(orders.getOrderName());
        payRecord.setUserId(orders.getUserId());
        payRecord.setCurrency("CNY");
        payRecord.setTotalPrice(orders.getTotalPrice());
        payRecord.setStatus("601001"); //未支付
        xcPayRecordMapper.insert(payRecord);
        return payRecord;
    }
}
